// ============================================================================
// FileName: NetServices.cs
//
// Description:
// Contains wrappers to access the functionality of the underlying operating
// system.
//
// Author(s):
// Aaron Clauson
//
// History:
// 26 Dec 2005	Aaron Clauson	Created.
// ============================================================================

using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;

#if UNITTEST
using NUnit.Framework;
#endif

namespace CN.Sys.Net
{
	public class NetServices
	{
        public const int UDP_PORT_START = 1025;
        public const int UDP_PORT_END = 65535;

        public static UdpClient CreateRandomUDPListener(IPAddress localAddress, out IPEndPoint localEndPoint)
        {
            return CreateRandomUDPListener(localAddress, UDP_PORT_START, UDP_PORT_END, null, out localEndPoint);
        }

        public static UdpClient CreateRandomUDPListener(IPAddress localAddress, int start, int end, ArrayList inUsePorts, out IPEndPoint localEndPoint)
        {
            try
            {
                UdpClient randomClient = null;
                int attempts = 1;

                localEndPoint = null;

                while (attempts < 50)
                {
                    int port = Crypto.GetRandomInt(start, end);
                    if (inUsePorts == null || !inUsePorts.Contains(port))
                    {
                        try
                        {
                            localEndPoint = new IPEndPoint(localAddress, port);
                            randomClient = new UdpClient(localEndPoint);
                            break;
                        }
                        catch
                        {
                            //logger.Warn("Warning couldn't create UDP end point for " + localAddress + ":" + port + "." + excp.Message);
                        }

                        attempts++;
                    }
                }

                //logger.Debug("Attempts to create UDP end point for " + localAddress + ":" + port + " was " + attempts);

                return randomClient;
            }
            catch
            {
                throw new ApplicationException("Unable to create a random UDP listener between " + start + " and " + end);
            }
        }
		
		#region Unit tests.

		#if UNITTEST

		[TestFixture]
		public class OSServicesUnitTest
		{		
			[TestFixtureSetUp]
			public void Init()
			{			
				// Redirect the logger to the console for unit testing.
				//Log.ConfigureUnitTestLogging();
				//logger.Info("BackupFileUnitTest: Test Logger.");
			}

			[TestFixtureTearDown]
			public void Dispose()
			{			
				
			}

			/// <summary>
			/// Test calling the operating system "route print" command.
			/// </summary>
			[Test]
			public void TestCallRoute()
			{
				Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
				
				Assert.IsNotNull(CallRoute(), "The 'route print' command did not return anything.");
			}

			/// <summary>
			/// Test calling the operating system "ipconfig /all" command.
			/// </summary>
			[Test]
			public void TestCallIPConfig()
			{
				Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
				
				Assert.IsNotNull(CallIPConfig(), "The 'ipconfig /all' command did not return anything.");
			}

			/// <summary>
			/// Test calling the operating system "ping <host>" command.
			/// </summary>
			[Test]
			public void TestCallPing()
			{
				Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
				
				string host = "127.0.0.1";

				Assert.IsNotNull(CallPing(host), "The 'ping " + host + "' command did not return anything.");
			}


			/// <summary>
			/// Test calling the operating system "tracert <host>" command.
			/// </summary>
			[Test]
			//[Ignore("Takes a while.")]
			public void TestCallTracert()
			{
				Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
				
				string host = "10.128.1.138";
				string commandLine = "-h 10"; // Allow 10 hops to resolve.

				Assert.IsNotNull(CallTracert(host, commandLine), "The 'tracert " + host + " " + commandLine + "' command did not return anything.");
			}
		}

		#endif

		#endregion
	}
}
